home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_130 / mach / mach.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  38KB  |  1,200 lines

  1. /* Mach1.6a - Mouse Accelerator with Hotkey   **** 02-10-88 ****
  2.    MachClk1.2a - and clock with beeper and meter.
  3.  
  4.    Copyright 1988 by Brian Moats  @Polyglot Software.
  5.  
  6.    This program may be freely distributed providing that the copyright
  7.    notice and document file are included. It may not be used in any
  8.    commercial product without prior written permission.
  9.  
  10.  
  11.    run mach [nambscqwekp] hotkeystring hotkeystring...hotkeystring
  12.  
  13.    Arguments: All optional. Any order.
  14.  
  15.    -n     Accelerator factor where n >= 0 && n <=9.
  16.    -a     Switchs hotkey qualifier from Alternate to Amiga.
  17.    -m     Removes the trapping of left-amiga-m. (allows normal use)
  18.    -bnnn  Time delay before blanking screen. 0-999 minutes. 0 = no blank.
  19.    -s     Removes sunmouse.
  20.    -c     Removes click to front.
  21.    -q     Adds qualifier accumulating feature.
  22.    -w     Disables auto clock to front. Adds depth gadget.
  23.    -estr  Use str as execute command string. Default = NewCLI.
  24.    -knnn  nnn > 0 put clock left edge at nnn. If nnn = 0, don't use clock.
  25.    -tnn   Set beep time interval to every nn minutes.
  26.    -pnnnn Set online rate. nnnn = pennies per hour. Default = 475.
  27.  
  28.    Usage eg. Run Mach -3 -m -a -b10 df0: df1: copy dir\n rename "blank space"
  29.  
  30.   How to build this:
  31.   Simple (with Manx). I used version 3.4.
  32.  
  33.     cc machclk
  34.     ln machclk.o -lc
  35.  
  36.  
  37.  
  38.   Changes from version 1.6
  39.   1.  New toggle -w will disabled the auto clock to front and add an
  40.       (mostly) invisible depth gadget to the clock window.
  41.   2.  Fixed orphaned clock window resulting from rapid F8 toggling.
  42.  
  43.   Changes from version 1.5:
  44.   1.  Uses UpfrontLayer() instead of WindowToFront() for the clock to prevent
  45.       lockups. Before, I was keeping track of the left mouse button and
  46.       not doing a WindowToFront() if the button was down because you may
  47.       be holding an icon. But...WindowToFront() doesn't actually happen
  48.       until the next event and if it happened that that event was a left
  49.       button down on an icon, bingo! it locks up. Sigh...live and learn.
  50.   2.  Allocate 1 byte for null in hotkey and execute definitions.
  51.   3.  Changed double control feature. Now you use -q. When you do, any
  52.       shift, alternate, amiga or control key is added to the next non-
  53.       qualifier key. This is intended primarily for disabled people who
  54.       find it difficult, if not impossible, to hold down two or more keys
  55.       at once. This accumulates qualifiers so you can hit for example,
  56.       control, shift, alternate and then F1. This is the same as typing
  57.       them at the same time. Hitting Caps Lock will reset the accumulator.
  58.   4.  Return value (rv) changed to long. If there is an error and if
  59.       short, it will crash when run from Runback but will set the returncode
  60.       when run from Run. If long, it won't crash but won't set the returncode
  61.       when run from Run. ??? Any ideas?
  62.  
  63.  
  64.  
  65.   Problem: The uninstall "Control-Qualifier-F1" and the Instant Screen
  66.            Blanker don't work right if defined in a hotkey. e.g. \c\A\2
  67.            doesn't blank the screen and \c\A\1 doesn't uninstall.
  68.  
  69.  */
  70.  
  71. #define USINGCLOCK   /* take this out if you don't want the clock */
  72.  
  73. #include <devices/audio.h>
  74. #include <devices/input.h>
  75. #include <devices/inputevent.h>
  76. #include <devices/timer.h>
  77. #include <exec/types.h>
  78. #include <exec/interrupts.h>
  79. #include <exec/memory.h>
  80. #include <exec/ports.h>
  81. #include <graphics/gfxmacros.h>
  82. #include <intuition/intuitionbase.h>
  83. #include <libraries/dos.h>
  84. #include <functions.h>
  85.  
  86.  
  87.             /* key codes that we need */
  88. #define F1           0x50
  89. #define F2           0x51
  90. #define F3           0x52
  91. #define F4           0x53
  92. #define F5           0x54
  93. #define F6           0x55
  94. #define F7           0x56
  95. #define F8           0x57
  96. #define F9           0x58
  97. #define F10          0x59
  98. #define MCODE        0x37   /* "M" key code */
  99. #define ESC          0x45
  100. #define BACKSLASH    0x0d
  101. #define LSHIFT       0x60
  102. #define RSHIFT       0x61
  103. #define CTL          0x63
  104. #define LALT         0x64
  105. #define RALT         0x65
  106. #define LAMIGA       0x66
  107. #define RAMIGA       0x67
  108.  
  109.            /* event signals */
  110. #define QUIT         0x1
  111. #define HOTKEY       0x2
  112. #define ACCELERATE   0x4
  113. #define BACKSCREEN   0x8
  114. #define NEWCLI       0x10
  115. #define UNBLANK      0x20
  116. #define BLANK        0x40
  117. #define SUN          0x80
  118. #define CLICKTF      0x100
  119. #define CLOCK        0x200
  120.  
  121. #define FIVE_MINUTES 300         /* 300 seconds */
  122. #define WAIT_TIME    1000000L    /* 1 second (in micro seconds) */
  123.  
  124. #define CAPSRPTMASK     0x05fb  /* capslock & repeat masked */
  125. #define CTLCAPSRPTMASK  0x05f3  /* control, capslock and repeat masked */
  126.  
  127. #ifdef USINGCLOCK
  128. char info[] = "MachClk 1.2a  \xa9 1988 by Brian Moats @Polyglot Software.\n";
  129.  
  130. char usage[] = "\n\
  131. Usage: Run MachClk [nscmqawebktp] hotkeystring hotkeystring...hotkeystring\n\
  132.    -n     Acceleration factor. n >= 0 && n <=9.\n\
  133.    -s     Removes sunmouse.\n\
  134.    -c     Removes click to front.\n\
  135.    -m     Allows normal use of Left-Amiga-M.\n\
  136.    -q     Adds qualifier accumulating feature.\n\
  137.    -a     Set qualifier from Alternate to Amiga.\n\
  138.    -w     Disables auto clock to front. Adds depth gadget.\n\
  139.    -estr  Use str as execute command string. Default = NewCLI.\n\
  140.    -bnnn  Time delay before blanking screen. 0 = no blank.\n\
  141.    -knnn  nnn > 0 put clock left edge at nnn. If nnn = 0, don't use clock.\n\
  142.    -tnn   Set beep time interval to every nn minutes.\n\
  143.    -pnnnn Set online rate. nnnn = pennies per hour. Default = 475.\n\n\
  144. Control-Qualify-Function Key Toggles:\n\
  145. F1 Remove, F2 Instant Blank, F3 Sun Mouse, F4 ClickToFront,\n\
  146. F5 Screen Shuffler, F6 Qualifier Accumulator, F7 Alternate/Amiga,\n\
  147. F8 Clock, F9 Meter, F10 Meter Reset.\n\n";
  148.  
  149. char reminfo[] = ">>> Use Control-Qualifier-F1 to remove MachClk. <<<\n";
  150. char die[] = "MachClk 1.2a removed.\n";
  151. char updated[] = "MachClk 1.2a updated.\n";
  152. char failed[] = "MachClk 1.2a failed.\n";
  153.  
  154. #else /* Otherwise use this stuff */
  155.  
  156. char info[] = "Mach 1.6a  \xa9 1988 by Brian Moats @Polyglot Software.\n";
  157.  
  158. char usage[] = "\n\
  159. Usage: Run Mach [nscmqaeb] hotkeystring hotkeystring...hotkeystring\n\
  160.    -n    Acceleration factor. n >= 0 && n <=9.\n\
  161.    -s    Removes sunmouse.\n\
  162.    -c    Removes click to front.\n\
  163.    -m    Allows normal use of Left-Amiga-M.\n\
  164.    -q    Adds qualifier accumulating feature.\n\
  165.    -a    Set qualifier from Alternate to Amiga.\n\
  166.    -estr Use str as execute command string. Default = NewCLI.\n\
  167.    -bnnn Time delay before blanking screen. 0 = no blank.\n\n\
  168. Control-Qualify-Function Key Toggles:\n\
  169. F1 Remove, F2 Instant Blank, F3 Sun Mouse, F4 ClickToFront,\n\
  170. F5 Screen Shuffler, F6 Qualifier Accumulator, F7 Alternate/Amiga.\n\n";
  171.  
  172. char reminfo[] = ">>> Use Control-Qualifier-F1 to remove Mach. <<<\n";
  173. char die[] = "Mach 1.6a removed.\n";
  174. char updated[] = "Mach 1.6a updated.\n";
  175. char failed[] = "MachClk 1.6a failed.\n";
  176. #endif
  177.  
  178. char badarg[] = "\n>>> Bad arguments <<<\n";
  179.  
  180. char PortName[] = "Mach Port";
  181.  
  182. char DefECommand[] = "NewCLI >NIL: <NIL:";
  183.  
  184.  
  185.  
  186. short dx,dy;         /* mouse acceleration delta x y */
  187. short x,y;           /* sunmouse and clicktofront position */
  188.  
  189.              /* event info */
  190. short keyCount = 0;     /* # of function keys pressed in 1 event chain */
  191. short kt[10];           /* 10 function keys max */
  192. short event;            /* signal all of the above defined events */
  193. short lastcode = 0;     /* last keypressed code that was removed from event chain */
  194. long  sec,micro;        /* previous second and micro */
  195. short noevent;          /* # of seconds of no events */
  196. short buttonisdown = 0; /* maintain left button state */
  197.  
  198. short canClock = 1;     /* running the title bar clock */
  199. short canMeter = 0;     /* not showing online meter */
  200. short lastMin = 61;     /* init to impossible # of minutes */
  201.  
  202. short addQual = 0;      /* qualifier to add */
  203. short blanking = 0;     /* not blanking now */
  204.  
  205. struct MsgPort   *inputPort = NULL;
  206. struct IOStdReq  *inputReq = NULL;
  207. struct MsgPort   *TimerPort = NULL;
  208. struct Screen    *s,*blankS = NULL;
  209. struct Window    *mw = NULL;
  210. struct Layer     *ml;
  211. struct IntuitionBase *IntuitionBase = NULL;
  212. struct LayersBase    *LayersBase = NULL;
  213. struct GfxBase       *GfxBase = NULL;
  214. struct FileHandle    *msgfh, *nullfh = NULL;
  215.  
  216. struct NewScreen newScreen = {0,0,320,30,1,0,0,NULL,CUSTOMSCREEN,
  217.                               NULL,NULL,NULL,NULL};
  218.  
  219. struct timerequest Timer_Req;
  220. long   TimerSig,tdevice = 1;
  221.  
  222. struct InputEvent phoney;
  223.  
  224. struct HotInfo
  225.   {
  226.   struct Task *hotTask;
  227.   long  hotSig;
  228.   } hotStuff;
  229.  
  230. long signum = -1;
  231.  
  232. struct Interrupt handlerStuff;
  233.  
  234. /* This MsgPort holds all function key definitions and other variables that
  235.    can be changed by running the program again. */
  236.  
  237. struct defPort
  238.   {
  239.   struct MsgPort mp;
  240.   char * func[10];   /* pointers to 10 hotkey strings */
  241.   char * ECommand;   /* pointer to command to execute with qualifier esc */
  242.   short acc;         /* acceleration factor */
  243.   short ourLQual;    /* the qualifiers being used */
  244.   short ourRQual;
  245.   short canSun;      /* sunning toggle */
  246.   short canFront;    /* click to front toggle */
  247.   short canShuffle;  /* amiga-m toggle */
  248.   short canAddQuals; /* qualifier adding toggle */
  249.   short alternate;   /* alternate or amiga key toggle */
  250.   short blanktime;   /* how long to wait before blanking */
  251. #ifdef USINGCLOCK
  252.   short canCFront;   /* auto upfront clock window toggle */
  253.   short rate;        /* online rate */
  254.   short beepInterval; /* how long to wait between beeps */
  255. #endif
  256.   };
  257.  
  258. struct defPort *defPortPtr;
  259.  
  260. char defPortName[] = "Definition Port";
  261.  
  262. short updating = 0; /* set to 1 if we updated (actually just found) defPort. */
  263.  
  264. /* Clock stuff */
  265.  
  266. #ifdef USINGCLOCK
  267.  
  268. #define SCREENWIDTH    640
  269. #define WINDOWWIDTH    346
  270. #define LEFTEDGE       SCREENWIDTH-54-WINDOWWIDTH
  271.  
  272. struct NewWindow newWindow = {
  273.   LEFTEDGE, 0,
  274.   WINDOWWIDTH, 10,
  275.   -1, -1,
  276.   0,          /* No IDCMP messages */
  277.   WINDOWDRAG | SMART_REFRESH | NOCAREREFRESH,
  278.   NULL, NULL, NULL, NULL, NULL,
  279.   0, 0, 0, 0,
  280.   WBENCHSCREEN
  281.   };
  282.  
  283. char TimeBuffer[52];
  284.  
  285. struct IntuiText TimeText = {1,0,JAM2,0,0, NULL, (UBYTE *)TimeBuffer, NULL };
  286.  
  287. struct Window *ClockWindow = NULL;
  288. short clockEdge = LEFTEDGE;      /* default position */
  289.  
  290. short cost;   /* online costs */
  291.  
  292. #endif
  293.  
  294. /* end of clock stuff */
  295.  
  296.  
  297.  
  298.           /* character translation table. Key codes in ascii order with bit 8 */
  299.           /* set for upper case. e.g. Shift 1 is exclamation mark and is  */
  300.           /* key code 01, 2nd entry in table with bit 8 set. 0x101 */
  301. USHORT keytran[96] =
  302.  {0x140,0x101,0x12a,0x103,0x104,0x105,0x107,0x12a,0x109,0x10a,
  303.   0x108,0x10c,0x38,0x0b,0x39,0x3a,0x0a,0x01,0x02,0x03,
  304.   0x04,0x05,0x06,0x07,0x08,0x09,0x129,0x29,0x138,0x0c,
  305.   0x139,0x13a,0x102,0x120,0x135,0x133,0x122,
  306.   0x112,0x123,0x124,0x125,0x117,0x126,0x127,0x128,0x137,0x136,0x118,
  307.   0x119,0x110,0x113,0x121,0x114,0x116,0x134,0x111,0x132,0x115,0x131,0x1a,
  308.   0x0d,0x1c,0x106,0x10b,0x00,0x20,0x35,0x33,0x22,0x12,
  309.   0x23,0x24,0x25,0x17,0x26,0x27,0x28,0x37,0x36,0x18,
  310.   0x19,0x10,0x13,0x21,0x14,0x16,0x34,0x11,0x32,0x15,
  311.   0x31,0x11a,0x10d,0x11b,0x100};
  312.  
  313.  
  314.  
  315. void HandlerInterface()
  316.   {
  317. #asm
  318.  
  319.   movem.l a4,-(sp)        ;Manx small code/small data needs to
  320.   jsr _geta4#             ;set up a4 to get at global data.
  321.   movem.l   A0/A1,-(sp)
  322.   jsr       _myhandler
  323.   addq.l    #8,A7
  324.   movem.l (sp)+,a4        ;Manx needs this to.
  325.                           ;No rts. Manx adds it.
  326. #endasm
  327.   }
  328.  
  329. /* The C handler routine.
  330.    It's pretty long but each event is actually taken care of with just
  331.    a few decisions. */
  332.  
  333.  
  334. struct InputEvent *myhandler(ev1, hotStuff)
  335.   struct InputEvent *ev1;
  336.   struct HotInfo *hotStuff;
  337.   {
  338.   struct InputEvent *ev, *last;
  339.   short removeit;
  340.   short evcode,evqual;
  341.  
  342.   event = 0;
  343.   Forbid();
  344.   for (ev=ev1,last = NULL; ev; ev=ev->ie_NextEvent)
  345.     {
  346.     evcode = ev->ie_Code;        /* cause these are accessed so often... */
  347.     evqual = ev->ie_Qualifier;   /* ...it saves bytes to get'em once */
  348.     removeit = 0;
  349.  
  350.     if ((ev->ie_Class != IECLASS_TIMER))
  351.       {
  352.       noevent = 0;
  353.       if (blanking)
  354.         event |= UNBLANK; /* Not TIMER and screen is blank, need to un-blank */
  355.  
  356.       if (ev->ie_Class == IECLASS_RAWKEY)
  357.         if (evcode >= 0x80)
  358.           {
  359.           event &= !UNBLANK;    /* BUT don't unblank on upkey */
  360.           if (evcode == (lastcode | 0x80)) /* remove if keypressed was removed */
  361.             {
  362.             removeit = 1;
  363.             lastcode = 0;
  364.             }
  365.           }
  366.         else  /* This is where we collect qualifiers to add */
  367.           {
  368.           if (defPortPtr->canAddQuals)
  369.             if ((evcode >= LSHIFT) && (evcode <= RAMIGA))
  370.               {
  371.               lastcode = evcode;
  372.               removeit = 1;
  373.               switch (evcode)
  374.                 {
  375.                 case LSHIFT:
  376.                   addQual |= IEQUALIFIER_LSHIFT;
  377.                   break;
  378.                 case RSHIFT:
  379.                   addQual |= IEQUALIFIER_RSHIFT;
  380.                   break;
  381.                 case CTL:
  382.                   addQual |= IEQUALIFIER_CONTROL;
  383.                   break;
  384.                 case LALT:
  385.                   addQual |= IEQUALIFIER_LALT;
  386.                   break;
  387.                 case RALT:
  388.                   addQual |= IEQUALIFIER_RALT;
  389.                   break;
  390.                 case LAMIGA:
  391.                   addQual |= IEQUALIFIER_LCOMMAND;
  392.                   break;
  393.                 case RAMIGA:
  394.                   addQual |= IEQUALIFIER_RCOMMAND;
  395.                   break;
  396.                 default:
  397.                   lastcode = 0;
  398.                   removeit = 0;
  399.                   addQual = 0;   /* Caps Lock gets here so lets nullify all */
  400.                   break;         /* qualifiers. */
  401.                 }
  402.               }
  403.             else         /* if code is not alt, amiga or shift */
  404.               {          /* add any qualifiers that there may be. */
  405.               evqual |= addQual;
  406.               ev->ie_Qualifier |= addQual;
  407.               addQual = 0;
  408.               }
  409.  
  410.           if (((evcode >= F1) && (evcode <= F10)) || (evcode == ESC))
  411.             {
  412.             if (((evqual & CTLCAPSRPTMASK) == defPortPtr->ourLQual) ||
  413.                 ((evqual & CTLCAPSRPTMASK) == defPortPtr->ourRQual))
  414.               {
  415.               lastcode = evcode;
  416.               if (evqual & IEQUALIFIER_CONTROL)  /* qualifier+control+function */
  417.                 {
  418.                 switch (evcode)
  419.                   {
  420.                   case F1:
  421.                     removeit = 1;
  422.                     event |= QUIT;
  423.                     break;
  424.                   case F2:
  425.                     removeit = 1;
  426.                     event |= BLANK;
  427.                     break;
  428.                   case F3:
  429.                     removeit = 1;
  430.                     defPortPtr->canSun = !defPortPtr->canSun;
  431.                     break;
  432.                   case F4:
  433.                     removeit = 1;
  434.                     defPortPtr->canFront = !defPortPtr->canFront;
  435.                     break;
  436.                   case F5:
  437.                     removeit = 1;
  438.                     defPortPtr->canShuffle = !defPortPtr->canShuffle;
  439.                     break;
  440.                   case F6:
  441.                     removeit = 1;
  442.                     defPortPtr->canAddQuals = !defPortPtr->canAddQuals;
  443.                     break;
  444.                   case F7:
  445.                     removeit = 1;
  446.                     defPortPtr->alternate = !defPortPtr->alternate;
  447.                     if (defPortPtr->alternate)
  448.                       {
  449.                       defPortPtr->ourLQual = IEQUALIFIER_LALT;
  450.                       defPortPtr->ourRQual = IEQUALIFIER_RALT;
  451.                       }
  452.                     else
  453.                       {
  454.                       defPortPtr->ourLQual = IEQUALIFIER_LCOMMAND;
  455.                       defPortPtr->ourRQual = IEQUALIFIER_RCOMMAND;
  456.                       }
  457.                     break;
  458. #ifdef USINGCLOCK
  459.                   case F8:
  460.                     removeit = 1;
  461.                     event ^= CLOCK;
  462.                     break;
  463.                   case F9:
  464.                     removeit = 1;
  465.                     canMeter = !canMeter;
  466.                     break;
  467.                   case F10:
  468.                     removeit = 1;
  469.                     cost = 0;
  470.                     break;
  471. #endif
  472.                   default:
  473.                     lastcode = 0;   /* no down key we want to remove upkey of */
  474.                   }
  475.                 }
  476.               else                    /* qualifier + ESC or function */
  477.                 {
  478.                 if (evcode == ESC)
  479.                   {
  480.                   removeit = 1;
  481.                   event |= NEWCLI;
  482.                   }
  483.                 else
  484.                   {
  485.                   if (defPortPtr->func[evcode - F1])
  486.                     {
  487.                     removeit = 1;
  488.                     if (keyCount < 10)
  489.                       {
  490.                       kt[keyCount++] = evcode;  /* save f key */
  491.                       event |= HOTKEY;
  492.                       }
  493.                     }
  494.                   }
  495.                 }
  496.               }
  497.             }
  498.           else
  499.             if (defPortPtr->canShuffle && (evcode == MCODE) &&
  500.                ((evqual & IEQUALIFIER_LCOMMAND) == IEQUALIFIER_LCOMMAND))
  501.               {
  502.               lastcode = evcode;
  503.               removeit = 1;
  504.               event ^= BACKSCREEN;
  505.               }
  506.           }
  507. /* end of RAWKEY stuff */
  508.  
  509.       if (ev->ie_Class == IECLASS_RAWMOUSE)
  510.         {
  511.         if (evcode == IECODE_LBUTTON)  /* keep track of left button. Up or */
  512.           buttonisdown = 1; /* down. Don't sun mouse or send clock to front */
  513.                              /* when down */
  514.         if (defPortPtr->canSun || defPortPtr->canFront)
  515.           {
  516.           s = IntuitionBase->FirstScreen;
  517.           while (s && (s->MouseY < 0)) s = s->NextScreen;
  518.           if (s == NULL) s = IntuitionBase->ActiveScreen;
  519.  
  520.           x = s->MouseX + ev->ie_X;
  521.           y = s->MouseY + ev->ie_Y;
  522.  
  523.           if ((defPortPtr->canSun) && !buttonisdown) /* don't sun while button is down */
  524.             event |= SUN;
  525.  
  526.           if ((defPortPtr->canFront) && (ev->ie_Code == IECODE_LBUTTON))
  527.             event |= CLICKTF;
  528.           }
  529.  
  530.         if (evcode == (IECODE_LBUTTON | 0x80))  /* Now set button up if it is */
  531.           buttonisdown = 0;
  532.  
  533.         if ((ev->ie_TimeStamp.tv_secs == sec) &&
  534.            ((ev->ie_TimeStamp.tv_micro / 50000) == micro))
  535.           {
  536.           dx = ev->ie_X;  /* only accel if 2 mouse moves in 1/20 second */
  537.           dy = ev->ie_Y;
  538.           event |= ACCELERATE;
  539.           }
  540.         if (ev->ie_TimeStamp.tv_secs) /* writeevent sets sec=0 */
  541.           {
  542.           micro = ev->ie_TimeStamp.tv_micro / 50000;
  543.           sec = ev->ie_TimeStamp.tv_secs;
  544.           }
  545.         }
  546.       }    /* if not timer event */
  547.            /* all events get here */
  548.       if (removeit)
  549.         if (last == NULL)       /* remove from event chain */
  550.           ev1 = ev->ie_NextEvent;
  551.         else
  552.           last->ie_NextEvent = ev->ie_NextEvent;
  553.       else
  554.         last = ev;
  555.     }    /* for */
  556.   if (event)
  557.     Signal(hotStuff->hotTask,hotStuff->hotSig);
  558.   Permit();
  559.   return(ev1);
  560.   }
  561.  
  562.  
  563. main(argc, argv)
  564.   short argc;
  565.   char *argv[];
  566.   {
  567.   struct IntuiMessage *Msg;
  568.   long                class;
  569.   long                len;
  570.   short               i,j,f,c;
  571.  
  572.  
  573.   msgfh = Output();
  574.   if (msgfh)
  575.     {
  576.     (void)Write(msgfh,info,(long)sizeof(info));
  577.     if ((argv[1][0] == '?') || (argc < 2))
  578.       {
  579.       (void)Write(msgfh,usage,(long)sizeof(usage));
  580.       if (argc < 2)
  581.         (void)Write(msgfh,reminfo,(long)sizeof(reminfo));
  582.       exit(0);
  583.       }
  584.     }
  585.  
  586.   IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0L);
  587.   GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0L);
  588.   LayersBase = (struct LayersBase *) OpenLibrary("layers.library",0L);
  589.  
  590.   defPortPtr = (struct defPort *) FindPort(defPortName);
  591.   if (defPortPtr == NULL)
  592.     {
  593.     if ((defPortPtr = (struct defPort *) AllocMem((long)sizeof(struct defPort),MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  594.       exit(10);
  595.     defPortPtr->acc = 1;       /* default acceleration rate */
  596.     defPortPtr->ourLQual = IEQUALIFIER_LALT;
  597.     defPortPtr->ourRQual = IEQUALIFIER_RALT; /* Defaults to Alternate qualifiers */
  598.     defPortPtr->canSun = 1;
  599.     defPortPtr->canFront = 1;
  600.     defPortPtr->canShuffle = 1;
  601.     defPortPtr->canAddQuals = 0;
  602.     defPortPtr->alternate = 1;
  603.     defPortPtr->blanktime = FIVE_MINUTES;
  604. #ifdef USINGCLOCK
  605.     defPortPtr->canCFront = 1; /* can automatically bring clock to front */
  606.     defPortPtr->beepInterval = 15; /* minutes */
  607.     defPortPtr->rate = 475; /* default peoplelink rate */
  608. #endif
  609.     if ((defPortPtr->ECommand = AllocMem((long)sizeof(DefECommand),MEMF_PUBLIC)) != NULL)
  610.       strcpy(defPortPtr->ECommand,DefECommand);
  611.     }
  612.   else
  613.     updating = 1; /* Port found so we must be updating it */
  614.  
  615.   for (i = 1,f = 0; i < argc && f <= 9; i++)
  616.     if (argv[i][0] == '-')
  617.       {
  618.       j = 1;
  619.       while (argv[i][j])  /* parse multiple options with one leading "-" */
  620.         {
  621.         if ((argv[i][j] >= '0') && (argv[i][j] <= '9'))  /* Accelerating arg? */
  622.           defPortPtr->acc = (argv[i][j++] & 0x0f);
  623.         else
  624.           if ((argv[i][j] & 0x5f) == 'M')    /* Don't want screen shuffler? */
  625.             {
  626.             defPortPtr->canShuffle = 0;
  627.             j++;
  628.             }
  629.           else
  630.             if ((argv[i][j] & 0x5f) == 'A')   /* Want Amiga qualifier? */
  631.               {
  632.               defPortPtr->alternate = 0;
  633.               defPortPtr->ourLQual = IEQUALIFIER_LCOMMAND;
  634.               defPortPtr->ourRQual = IEQUALIFIER_RCOMMAND;
  635.               j++;
  636.               }
  637.             else
  638.               if ((argv[i][j] & 0x5f) == 'S')   /* Don't want sunmouse? */
  639.                 {
  640.                 defPortPtr->canSun = 0;
  641.                 j++;
  642.                 }
  643.               else
  644.                 if ((argv[i][j] & 0x5f) == 'C')   /* Don't want ClickToFront? */
  645.                   {
  646.                   defPortPtr->canFront = 0;
  647.                   j++;
  648.                   }
  649.                 else
  650.                   if ((argv[i][j] & 0x5f) == 'B')   /* Got blanking arg? */
  651.                     {
  652.                     defPortPtr->blanktime = atoi(&argv[i][j+1]) * 60;
  653.                     while (argv[i][++j]) ;
  654.                     }
  655.                   else
  656.                     if ((argv[i][j] & 0x5f) == 'Q') /* Want to add up qualifiers? */
  657.                       {
  658.                       defPortPtr->canAddQuals = 1;  /* this one defaults to off. */
  659.                       j++;
  660.                       }
  661.                     else
  662.                       if ((argv[i][j] & 0x5f) == 'E') /* Got execute command? */
  663.                         {
  664.                         if (defPortPtr->ECommand) /* free old command */
  665.                           FreeMem(defPortPtr->ECommand,(long)strlen(defPortPtr->ECommand)+1);
  666.                         if (defPortPtr->ECommand = AllocMem((long)strlen(&argv[i][j+1])+1,MEMF_PUBLIC))
  667.                           strcpy(defPortPtr->ECommand,&argv[i][j+1]);
  668.                         while (argv[i][++j]) ;
  669.                         }
  670. #ifdef USINGCLOCK
  671.                       else
  672.                         if ((argv[i][j] & 0x5f) == 'K') /* Clock stuff? */
  673.                           {
  674.                           clockEdge = atoi(&argv[i][j+1]);
  675.                           if (clockEdge == 0)   /* 0 or no number means no clock */
  676.                             canClock = 0;
  677.                           while (argv[i][++j]) ;
  678.                           }
  679.                         else
  680.                           if ((argv[i][j] & 0x5f) == 'T') /* Beep interval? */
  681.                             {
  682.                             defPortPtr->beepInterval = atoi(&argv[i][j+1]);
  683.                             while (argv[i][++j]) ;
  684.                             }
  685.                           else
  686.                             if ((argv[i][j] & 0x5f) == 'P') /* Penny watcher? */
  687.                               {
  688.                               defPortPtr->rate = atoi(&argv[i][j+1]);
  689.                               while (argv[i][++j]) ;
  690.                               }
  691.                             else
  692.                               if ((argv[i][j] & 0x5f) == 'W') /* Clock window autofront? */
  693.                                 {
  694.                                 defPortPtr->canCFront = 0;
  695.                                 j++;
  696.                                 }
  697. #endif
  698.                             else
  699.                               {
  700.                               if (msgfh)
  701.                                 {
  702.                                 Write(msgfh,badarg,(long)sizeof(badarg));
  703.                                 Write(msgfh,usage,(long)sizeof(usage));
  704.                                 }
  705.                               Uninstall(10L);
  706.                               }
  707.  
  708.         }
  709.       }
  710.     else  /* Not "-", must be hotkey definition. */
  711.           /* Set len equal to length of argv[i] + 1 for null if not a */
  712.           /* specific key given with +n. If +n, set len equal to length */
  713.           /* of argv[i] - 1. */
  714.       {
  715.       if (len = (long)strlen(argv[i]))
  716.         {
  717.         c = 0;
  718.         if (argv[i][0] == '+')  /* specific key? */
  719.           {
  720.           if (argv[i][1] >= '0' && argv[i][1] <= '9')
  721.             {
  722.             f = argv[i][1] - '0' - 1;
  723.             if (f < 0)
  724.               f = 9;
  725.             c = 2;   /* 1st char of definition */
  726.             len--;  /* less plus sign but keep 1 for null */
  727.             }
  728.           }
  729.         else
  730.           len++; /* add for null */
  731.  
  732.         if (defPortPtr->func[f]) /* free old definition */
  733.           FreeMem(defPortPtr->func[f],(long)strlen(defPortPtr->func[f])+1);
  734.         if (defPortPtr->func[f] = AllocMem(len,MEMF_PUBLIC))
  735.           strcpy(defPortPtr->func[f],&argv[i][c]);
  736.         }
  737.       f++;
  738.       }
  739.  
  740.   if (updating)    /* if we just updating, get out now */
  741.     Uninstall(0L);
  742.  
  743.   defPortPtr->mp.mp_Node.ln_Pri = 0;
  744.   defPortPtr->mp.mp_Node.ln_Type = NT_MSGPORT;
  745.   NewList(&(defPortPtr->mp.mp_MsgList));
  746.   defPortPtr->mp.mp_Node.ln_Name = (char *) &(defPortName);
  747.  
  748.   AddPort(defPortPtr); /* add our hotkey and definition port structure */
  749.  
  750.    /* Init HotStuff structure */
  751.   if((signum = AllocSignal((long)-1)) == -1)
  752.     Uninstall(11L);
  753.  
  754.   hotStuff.hotSig = 1 << signum;
  755.   hotStuff.hotTask = FindTask(NULL);
  756.  
  757.   /* and stuff to add the handler */
  758.   if(!(inputPort = CreatePort(PortName,0)))
  759.     Uninstall(12L);
  760.   if(!(inputReq = CreateStdIO(inputPort)))
  761.     Uninstall(13L);
  762.  
  763.   handlerStuff.is_Data = (APTR)&hotStuff;   /* shared data */
  764.   handlerStuff.is_Code = HandlerInterface;  /* assem entry */
  765.   handlerStuff.is_Node.ln_Pri = 55;         /* above Intuition */
  766.   handlerStuff.is_Node.ln_Name = "Mach Handler";
  767.  
  768.   if(OpenDevice("input.device",0L,inputReq,0L) != 0)
  769.     Uninstall(14L);
  770.  
  771.   inputReq->io_Command = IND_ADDHANDLER;
  772.   inputReq->io_Data = (APTR)&handlerStuff;
  773.  
  774.   DoIO(inputReq);
  775.  
  776.   nullfh = Open("NIL:",MODE_NEWFILE); /* used by Execute() */
  777.  
  778.   /* setup timer */
  779.  
  780.   if ((TimerPort = CreatePort("Timer Port", 0L)) == NULL)
  781.     Uninstall(15L);
  782.  
  783.   if ((tdevice = OpenDevice(TIMERNAME, UNIT_VBLANK, &Timer_Req, 0L)) != 0)
  784.     Uninstall(16L);
  785.   Timer_Req.tr_node.io_Message.mn_ReplyPort = TimerPort;
  786.   Timer_Req.tr_node.io_Command = TR_ADDREQUEST;
  787.   Timer_Req.tr_node.io_Flags = 0;
  788.   Timer_Req.tr_node.io_Error = 0;
  789.  
  790.   TimerSig = (1L << TimerPort->mp_SigBit);
  791.  
  792.   /* end of timer stuff */
  793.  
  794. #ifdef USINGCLOCK
  795.   if (canClock)
  796.     SetupClock();
  797.   DisplayTime();
  798. #endif
  799.  
  800.   (void)SetTaskPri(FindTask(NULL), 20L);
  801.  
  802.   QueTimer();
  803.  
  804.  /*************************************************************************
  805.                              MAIN EVENT LOOP
  806.  ***************************************************************************/
  807.  
  808.   for (;;)
  809.     {
  810.     Wait(hotStuff.hotSig | TimerSig);
  811.  
  812. #ifdef USINGCLOCK
  813.       if (event & CLOCK)
  814.         {
  815.         canClock = !canClock; /* Toggling it here prevents orphaned windows */
  816.         if (canClock)
  817.           SetupClock();
  818.         else
  819.           KillClock();
  820.         }
  821.  
  822. #endif
  823.       if ((Msg = (struct IntuiMessage *)GetMsg(TimerPort)) || (event & BLANK))
  824.         {
  825.         if (Msg)
  826.           {
  827.           QueTimer();
  828. #ifdef USINGCLOCK
  829.           DisplayTime();
  830. #endif
  831.           }
  832.         if ((((++noevent >= defPortPtr->blanktime) && defPortPtr->blanktime) ||
  833.            (event & BLANK)) && !blanking)
  834.           if ((blankS = OpenScreen(&newScreen)) != NULL)
  835.             {
  836.             SetRGB4(&(blankS->ViewPort),0L,0L,0L,0L);
  837.             OFF_DISPLAY;
  838.             blanking = 1;
  839.             }
  840.         }
  841.  
  842.     if (event & UNBLANK)
  843.       if ((blanking) && (blankS))
  844.         {
  845.         blanking = 0;
  846.         (void)CloseScreen(blankS);
  847.         ON_DISPLAY;
  848.         }
  849.  
  850.     i = 0;
  851.     if (event & HOTKEY)
  852.       {
  853.       while (i < keyCount)  /*may be more than 1 function key pressed */
  854.         WriteHotString(i++);
  855.       keyCount = 0;
  856.       }
  857.  
  858.     if (defPortPtr->acc && (event & ACCELERATE))
  859.       Accelerate();
  860.  
  861.     if (event & BACKSCREEN)
  862.       {
  863.       Forbid();
  864.       if (s = IntuitionBase->FirstScreen)
  865.         (void)ScreenToBack(s);
  866.       Permit();
  867.       }
  868.  
  869.     if (event & NEWCLI)
  870.       {
  871.       WBenchToFront();
  872.       Execute(defPortPtr->ECommand,nullfh,nullfh);
  873.       }
  874.  
  875.     if (event & (SUN | CLICKTF))
  876.       {
  877.       ml = WhichLayer(&(s->LayerInfo),(long)x,(long)y);
  878.       if (ml && (mw = (struct Window *)ml->Window))
  879.         {
  880.         if ( event & SUN)
  881.           if (mw != IntuitionBase->ActiveWindow)
  882.             (void)ActivateWindow(mw);
  883.  
  884.         if (event & CLICKTF)
  885.           {
  886.           if (!(mw->Flags & BACKDROP))
  887.             (void)WindowToFront(mw);
  888.           }
  889.         }
  890.       }
  891.  
  892.     if (event & QUIT)
  893.       Uninstall(0L);     /* all done...never to return */
  894.  
  895.     }  /* for(;;) */
  896.   }  /* main() */
  897.  
  898.  /************************************************************************/
  899.  
  900.  
  901. QueTimer()
  902.   {
  903.   Timer_Req.tr_time.tv_secs = 0;
  904.   Timer_Req.tr_time.tv_micro = WAIT_TIME;
  905.   SendIO(&Timer_Req.tr_node);
  906.   }
  907.  
  908.  
  909. #ifdef USINGCLOCK
  910.  
  911. SetupClock()
  912.   {
  913.   newWindow.LeftEdge = clockEdge;
  914.   if (defPortPtr->canCFront)
  915.     newWindow.Flags &= ~WINDOWDEPTH;
  916.   else
  917.     newWindow.Flags |= WINDOWDEPTH;
  918.   if (!(ClockWindow = OpenWindow(&newWindow)))
  919.     canClock = 0;  /* if can't then just disable clock */
  920.   }
  921.  
  922. KillClock()
  923.   {
  924.   if (ClockWindow)
  925.     CloseWindow(ClockWindow);
  926.   ClockWindow = NULL;
  927.   canClock = 0;
  928.   }
  929.  
  930. DisplayTime()
  931.   {
  932.   long  hours, minutes, seconds;
  933.   long  chipfree, fastfree;
  934.   struct DateStamp time;
  935.  
  936.   if (canClock)
  937.     {
  938.     DateStamp(&time);
  939.     chipfree = AvailMem(MEMF_CHIP) >> 10;
  940.     fastfree = AvailMem(MEMF_FAST) >> 10;
  941.     hours = time.ds_Minute / 60 ;
  942.     if (hours >= 13)
  943.       hours = (hours % 13)+1; /* don't want 24 hr. */
  944.     minutes = time.ds_Minute % 60 ;
  945.     seconds = time.ds_Tick / TICKS_PER_SECOND;
  946.     if (!(seconds % 4) && defPortPtr->canCFront)     /* don't do to often. */
  947.       {
  948.       Forbid();
  949.       ml = WhichLayer(&(ClockWindow->WScreen->LayerInfo),(long)ClockWindow->LeftEdge,(long)ClockWindow->TopEdge+1);
  950.       if ((ml->Window != ClockWindow) && !buttonisdown)
  951.         UpfrontLayer(&(ClockWindow->WScreen->LayerInfo),ClockWindow->WLayer);
  952.     /* Don't use windowtofront because it locks up if holding
  953.        an icon because it waits for an event which might be
  954.        a button down on an icon! */
  955.       Permit();
  956.       }
  957.     if (canMeter)
  958.       sprintf(TimeBuffer, "[     ] Chip: %3ld  Fast:%4ld  Cost: $%2d.%02d ",
  959.                              chipfree,fastfree,cost/100,cost % 100);
  960.     else
  961.       sprintf(TimeBuffer, "[     ] Chip: %3ld  Fast:%4ld  Time:%2ld:%02ld:%02ld",
  962.                              chipfree,fastfree,hours,minutes,seconds);
  963.     if (lastMin != minutes)
  964.       {
  965.       lastMin = minutes;
  966.       cost = cost + (((defPortPtr->rate / 6) + (defPortPtr->rate % 6)) / 10);
  967.       }
  968.  
  969.     if (defPortPtr->canSun) TimeBuffer[1] = 's';    /* put in current toggles */
  970.     if (defPortPtr->canFront) TimeBuffer[2] = 'c';
  971.     if (defPortPtr->canShuffle) TimeBuffer[3] = 'm';
  972.     if (defPortPtr->canAddQuals) TimeBuffer[4] = 'q';
  973.     if (!(defPortPtr->alternate)) TimeBuffer[5] = 'a';
  974.  
  975.     PrintIText(ClockWindow->RPort, &TimeText, 1L, 1L);
  976.     if ((seconds == 0) && (defPortPtr->beepInterval) && ((minutes % defPortPtr->beepInterval)==0))
  977.       Beep();
  978.     }
  979.   }
  980.  
  981.  
  982. Beep()
  983.   {
  984.   struct IOAudio sound;
  985.   char * sData;
  986.   short i;
  987.   long soundUnit;
  988.  
  989.   if (sound.ioa_Request.io_Message.mn_ReplyPort = CreatePort("Beep Port",0L))
  990.     {
  991.     soundUnit = 0x01020408;
  992.     sound.ioa_Request.io_Message.mn_Node.ln_Pri = 10;
  993.     sound.ioa_Data = (UBYTE *) &soundUnit;
  994.     sound.ioa_Length = 4;
  995.  
  996.     if (OpenDevice(AUDIONAME,0L,&sound.ioa_Request,0L) == NULL)
  997.       {
  998.  
  999.       if ((sData = AllocMem(64L,MEMF_CHIP | MEMF_CLEAR)) != NULL)
  1000.         {
  1001.         for (i = 1;i < 64;i++)
  1002.           sData[i] = i;
  1003.  
  1004.         sound.ioa_Request.io_Command = CMD_WRITE;
  1005.         sound.ioa_Request.io_Flags = ADIOF_PERVOL;
  1006.         sound.ioa_Data = (UBYTE *) sData;
  1007.         sound.ioa_Cycles = 50;
  1008.         sound.ioa_Length = 64;
  1009.         sound.ioa_Period = 128; /* use a higher number for a lower tone */
  1010.         sound.ioa_Volume = 64;
  1011.  
  1012.         BeginIO(&sound.ioa_Request);
  1013.         WaitIO(&sound.ioa_Request);
  1014.  
  1015.         FreeMem(sData,64L);
  1016.         }
  1017.       CloseDevice(&sound.ioa_Request);
  1018.       }
  1019.     DeletePort(sound.ioa_Request.io_Message.mn_ReplyPort);
  1020.     }
  1021.   }
  1022. #endif
  1023.  
  1024. #define ASCIIBIAS 0x20
  1025. #define SHIFTBIT  0x100
  1026. #define RETURN    0x44
  1027.  
  1028. WriteHotString(e)
  1029.   short e;         /* key table entry */
  1030.   {
  1031.   short k,j,outkey,outqual;
  1032.  
  1033.   k = 0;
  1034.   j = kt[e]-F1;        /* 1-10 from the function key code */
  1035.   if (!(defPortPtr->func[j])) return;
  1036.   while (defPortPtr->func[j][k])
  1037.     {
  1038.     outkey = 0;
  1039.     outqual = 0;
  1040.     while ((defPortPtr->func[j][k] == '\\') && (outkey == 0))
  1041.       {
  1042.       switch (defPortPtr->func[j][++k])
  1043.         {
  1044.         case 'N':
  1045.         case 'n':
  1046.           outkey = RETURN;
  1047.           ++k;
  1048.           break;
  1049.         case 'C':
  1050.         case 'c':
  1051.           outqual |= IEQUALIFIER_CONTROL;
  1052.           ++k;
  1053.           break;
  1054.         case 'a':
  1055.           outqual |= IEQUALIFIER_LALT;
  1056.           ++k;
  1057.           break;
  1058.         case 'A':
  1059.           outqual |= IEQUALIFIER_LCOMMAND;
  1060.           ++k;
  1061.           break;
  1062.         case 's':
  1063.         case 'S':
  1064.           outqual |= IEQUALIFIER_LSHIFT;
  1065.           ++k;
  1066.           break;
  1067.         case '\\':
  1068.           outkey = BACKSLASH;
  1069.           ++k;
  1070.           break;
  1071.         default:
  1072.           if ((defPortPtr->func[j][k] >= '0') && (defPortPtr->func[j][k] <= '9'))  /* Function key? */
  1073.             outkey = defPortPtr->func[j][k++] + 0x1f;  /* translate '1' - '9' to F1 - F9 */
  1074.           if (outkey == 0x4f)
  1075.             outkey = 0x59;     /* translate '0' to F10 */
  1076.           break;
  1077.         }
  1078.       }
  1079.     if (outkey == 0)  /* then didn't get return or function key or "\" */
  1080.       {               /* translate letter into keycode and qualifier */
  1081.       outkey = (keytran[(defPortPtr->func[j][k] - ASCIIBIAS)]);
  1082.       outqual |= (outkey & SHIFTBIT) >> 8; /* add shift qualifier if present */
  1083.       outkey &= 0x7f;                      /* then strip shiftbit */
  1084.       ++k;
  1085.       }
  1086.     WriteKey(outkey,outqual);               /* send it pressed down */
  1087.     WriteKey(outkey | 0x80,outqual);        /* and up */
  1088.     }
  1089.   }
  1090.  
  1091. WriteKey(c,q)
  1092.   short c,q;
  1093.   {
  1094.   inputReq->io_Command = IND_WRITEEVENT;
  1095.   inputReq->io_Flags = 0;
  1096.   inputReq->io_Length = sizeof(struct InputEvent);
  1097.   inputReq->io_Data = (APTR)&phoney;
  1098.  
  1099.   phoney.ie_NextEvent = NULL;
  1100.   phoney.ie_Class = IECLASS_RAWKEY;
  1101.   phoney.ie_TimeStamp.tv_secs = 0;
  1102.   phoney.ie_TimeStamp.tv_micro = 0;
  1103.   phoney.ie_Code = c;
  1104.   phoney.ie_Qualifier = q;
  1105.   phoney.ie_X = 0;
  1106.   phoney.ie_Y = 0;
  1107.   DoIO(inputReq);
  1108.   }
  1109.  
  1110. Accelerate()
  1111.   {
  1112.   inputReq->io_Command = IND_WRITEEVENT;
  1113.   inputReq->io_Flags = 0;
  1114.   inputReq->io_Length = sizeof(struct InputEvent);
  1115.   inputReq->io_Data = (APTR)&phoney;
  1116.  
  1117.   phoney.ie_NextEvent = NULL;
  1118.   phoney.ie_Class = IECLASS_RAWMOUSE;
  1119.   phoney.ie_TimeStamp.tv_secs = 0;
  1120.   phoney.ie_TimeStamp.tv_micro = 0;
  1121.   phoney.ie_Code = IECODE_NOBUTTON;
  1122.   phoney.ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
  1123.   phoney.ie_X = (dx * defPortPtr->acc) / 2;
  1124.   phoney.ie_Y = (dy * defPortPtr->acc) / 3;
  1125.   DoIO(inputReq);
  1126.   }
  1127.  
  1128. Uninstall(rv)
  1129.   long rv;
  1130.   {
  1131.   short i;
  1132.  
  1133.   if (msgfh)
  1134.     if (event & QUIT)
  1135.       (void)Write(msgfh,die,(long)sizeof(die));
  1136.     else
  1137.       if (rv)
  1138.         (void)Write(msgfh,failed,(long)sizeof(failed));
  1139.       else
  1140.         if (updating)
  1141.           (void)Write(msgfh,updated,(long)sizeof(updated));
  1142.  
  1143.   if (!updating)
  1144.     {
  1145.     if (inputReq)      /* remove the handler */
  1146.       {
  1147.       inputReq->io_Command = IND_REMHANDLER;
  1148.       inputReq->io_Data = (APTR)&handlerStuff;
  1149.       DoIO(inputReq);
  1150.  
  1151.       CloseDevice(inputReq);
  1152.       DeleteStdIO(inputReq);
  1153.       }
  1154.  
  1155.    /* close, delete and free other stuff */
  1156.  
  1157.     if (nullfh)       Close(nullfh);
  1158.     if (inputPort)    DeletePort(inputPort);
  1159.     if (signum > -1)  FreeSignal(signum);
  1160.  
  1161.     if (tdevice == 0)
  1162.       {
  1163.       AbortIO(&Timer_Req.tr_node);
  1164.       CloseDevice(&Timer_Req);
  1165.       }
  1166.  
  1167.     if (TimerPort)
  1168.       DeletePort(TimerPort);
  1169.  
  1170. #ifdef USINGCLOCK
  1171.     if (canClock)
  1172.       KillClock();
  1173. #endif
  1174.  
  1175.     if (defPortPtr)
  1176.       {                       /* Free hotkey definitions */
  1177.       for (i=0;i<10;i++)
  1178.         if (defPortPtr->func[i])
  1179.           FreeMem(defPortPtr->func[i],(long)strlen(defPortPtr->func[i])+1);
  1180.  
  1181.                              /* Free Execute Command string */
  1182.       if (defPortPtr->ECommand)
  1183.         FreeMem(defPortPtr->ECommand,(long)strlen(defPortPtr->ECommand)+1);
  1184.  
  1185.       if (defPortPtr->mp.mp_Node.ln_Name)
  1186.         RemPort(defPortPtr);
  1187.       FreeMem(defPortPtr,(long)sizeof(struct defPort));
  1188.       }
  1189.     }
  1190.  
  1191.   if (IntuitionBase)
  1192.     CloseLibrary(IntuitionBase);
  1193.   if (GfxBase)
  1194.     CloseLibrary(GfxBase);
  1195.   if (LayersBase)
  1196.     CloseLibrary(LayersBase);
  1197.   exit(rv);
  1198.   }
  1199.  
  1200.